package edu.bu.met683.TravelDroid.data;

import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;

import android.content.res.Resources;
import android.util.Log;

import com.google.android.maps.GeoPoint;

import edu.bu.met683.TravelDroid.R;

/**
 * This class is the java object representation of a Tour that traveldroid
 * provides to the user.
 */
public class Tour 
{

	// Class Metadata
	private static final String CLASS_TAG = Tour.class.getSimpleName();
	private static final String TOUR_XML_TAG = "tour";
	private static final String TOUR_NAME_XML_TAG = "name";
	private static final String TOUR_DESCRIPTION_XML_TAG = "description";
	private static final String TOUR_LENGTH_XML_TAG = "length";
	private static final String TOUR_POI_XML_TAG = "pois";
	private static final String TOUR_PLACEMARK_XML_TAG = "Placemark";
	private static final String TOUR_ROUTE_XML_TAG = "route";
	private static final String TOUR_LINE_XML_TAG = "LineString";

	// Member Variables
	private String name;
	private String description;
	private double length;
	private List<PointOfInterest> poiList;
	private List<GeoPoint> routePoints;
	private double proximity = 0;
	

	/**
	 * Constructor that accepts all the fields of a tour.
	 * 
	 * @param n
	 * @param d
	 * @param p
	 * @param r
	 */
	private Tour(String n, String d, double l, List<PointOfInterest> p,
			List<GeoPoint> r) {
		name = n;
		description = d;
		length = l;
		poiList = p;
		routePoints = r;
	}

	/**
	 * Constructor that uses an XML Parser to generate a Tour object.
	 * 
	 * @param parser
	 */
	private Tour(XmlPullParser parser) {
		poiList = new ArrayList<PointOfInterest>();
		routePoints = new ArrayList<GeoPoint>();

		try {
			String tag = parser.getName();

			while (!tag.equals(TOUR_XML_TAG)) {

				if ((tag != null) && tag.equals(TOUR_NAME_XML_TAG)) {
					parser.next();
					name = parser.getText();
					parser.next();
				} else if ((tag != null)
						&& tag.equals(TOUR_DESCRIPTION_XML_TAG)) {
					parser.next();
					description = parser.getText();
					parser.next();
				} else if ((tag != null) && tag.equals(TOUR_LENGTH_XML_TAG)) {
					parser.next();
					length = Double.parseDouble(parser.getText());
					parser.next();
				} else if ((tag != null) && tag.equals(TOUR_POI_XML_TAG)) {
					parser.next();
					tag = parser.getName();

					while ((tag != null) && !tag.equals(TOUR_POI_XML_TAG)) {
						if ((tag != null) && tag.equals(TOUR_PLACEMARK_XML_TAG)) {
							parser.next();

							PointOfInterest poi = new PointOfInterest(parser);
							poiList.add(poi);

							tag = parser.getName();
						}
					}
				} else if (tag != null && tag.equals(TOUR_ROUTE_XML_TAG)) {
					parser.next();
					tag = parser.getName();

					if ((tag != null) && tag.equals(TOUR_LINE_XML_TAG)) {
						parser.next();
						parser.next();

						// Split the string into each point
						String lineString = parser.getText();
						String[] pointStrings = lineString.split(" ");

						// Convert each string to a point and add to the route
						for (String pointString : pointStrings) {
							GeoPoint point = DataUtilities
									.convertStringToGeoPoint(pointString);
							routePoints.add(point);
						}

						// Skip Coordinate and Linestring Tags
						parser.next();
						parser.next();
					}
					parser.next();
				} else {
					parser.next();
					parser.next();
					Log.w(CLASS_TAG, "Uknown XML Tag Encountered: "
							+ (tag != null ? tag : "null"));
				}
				parser.next();
				tag = parser.getName();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Gets the name of the tour.
	 * 
	 * @return
	 */
	public String getName() {
		return name;
	}

	/**
	 * Gets the description of the Tour
	 * 
	 * @return
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * Gets the length of the Tour
	 * 
	 * @return
	 */
	public double getLength() {
		return length;
	}

	/**
	 * Gets the Points of Interest for the tour.
	 * 
	 * @return
	 */
	public List<PointOfInterest> getPoiList() {
		return poiList;
	}

	/**
	 * Gets the list of points that make up the Tour's route.
	 * 
	 * @return
	 */
	public List<GeoPoint> getRoutePoints() {
		return routePoints;
	}

	/**
	 * Gets the starting location for the Tour.
	 * 
	 * @return a GeoPoint that represents the start point for the tour.
	 */
	public GeoPoint getStartPoint() {
		if ((routePoints != null) && (routePoints.size() > 0)) {
			return routePoints.get(0);
		}
		return null;
	}

	/**
	 * Loads the list of available Tours from the Tours.xml file.
	 * 
	 * @param resources
	 * @return
	 */
	public static List<Tour> loadTourData(Resources resources) {

		// Create parser for tour file
		XmlPullParser parser = resources.getXml(R.xml.tours);

		// Create a new list to hold the tours
		List<Tour> tours = new ArrayList<Tour>();

		try {
			while (parser.next() != XmlPullParser.END_DOCUMENT) {
				String tag = parser.getName();

				if ((tag != null) && tag.equals(TOUR_XML_TAG)) {
					parser.next();

					// Create a new tour object and add to list
					Tour newTour = new Tour(parser);
					tours.add(newTour);
				}
			}
		} catch (Exception e) {
			Log.e(CLASS_TAG, e.getMessage(), e);
		}

		return tours;
	}
	
	public double getProximity() {
		return proximity;
	}

	public void setProximity(double proximity) {
		this.proximity = proximity;
	}
	
	/**
	 * Retrieves the latest Point Of Interest
	 *
	 * @param name
	 * @return
	 */
	public PointOfInterest getPOIByName(String name){
		PointOfInterest result = null;
		
		for( PointOfInterest poi : poiList ){
			if( poi.getName().equals(name)){
				result = poi;
				break;
			}
		}
		
		return result;
	}
}


